package com.breeze.media.codec.teams;

import android.media.MediaCodec;
import android.media.MediaCrypto;
import android.media.MediaFormat;
import android.os.Build;
import android.os.Handler;
import android.os.HandlerThread;
import android.util.Log;
import android.view.Surface;

import java.nio.ByteBuffer;
import java.util.concurrent.CountDownLatch;

public class DummyMediaCodec extends MediaCodec.Callback {
    private static final int BITRATE = 2000000;
    private static final int ExynosDecoderDriver = 180315;
    private static final int FRAME_RATE = 30;
    private static final int IFRAME_INTERVAL = 1;
    private static final String KEY_DEC_VER = "-ext-dec-caps-vt-driver-version.number";
    private static final String KEY_ENC_MAXDS = "-ext-enc-caps-preprocess.max-downscale-factor";
    private static final String KEY_ENC_MAXLTR = "-ext-enc-caps-ltr.max-count";
    private static final String KEY_ENC_ROT = "-ext-enc-caps-preprocess.rotation";
    private static final String KEY_ENC_TLYER = "-ext-enc-caps-temporal-layers.max-p-count";
    private static final String KEY_ENC_VER = "-ext-enc-caps-vt-driver-version.number";
    public final CountDownLatch callbackCountDown = new CountDownLatch(1);
    private HandlerThread callbackThread;
    private Handler callbackhandler;
    private String extPrefix;
    private MediaCodec mDec;
    private boolean mDecConfigured;
    public MediaFormat mDecOutputFormat = null;
    private boolean mDone = false;
    private MediaCodec mEnc;
    public MediaFormat mEncOutputFormat = null;
    private long mInFrameCount = 0;
    private MediaFormat mInputFormat;
    private boolean mIsEncoderOnly;
    private boolean mIsExynos;
    private long mOutFrameCount = 0;
    private long pts = 0;

    public DummyMediaCodec(boolean encoderOnly, boolean exynos) {
        this.mIsEncoderOnly = encoderOnly;
        this.mIsExynos = exynos;
    }

    public void init(int width, int height, String extPrefix) throws Exception {
        MediaFormat mediaFormat;
        Log.d(Commons.TAG, "Build: BOARD=" + Build.BOARD);
        Log.d(Commons.TAG, "Build: Device=" + Build.DEVICE);
        Log.d(Commons.TAG, "Build: PROD=" + Build.PRODUCT);
        Log.d(Commons.TAG, "init encoder");
        MediaFormat mediaFormat2 = this.mInputFormat;
        if (mediaFormat2 == null) {
            mediaFormat = MediaFormat.createVideoFormat(CodecUtils.MEDIA_TYPE, width, height);
        } else {
            mediaFormat = MediaFormat.createVideoFormat(CodecUtils.MEDIA_TYPE, mediaFormat2.getInteger("width"), this.mInputFormat.getInteger("height"));
        }
        mediaFormat.setInteger("bitrate", BITRATE);
        int frameRate = 30;
        MediaFormat mediaFormat3 = this.mInputFormat;
        if (mediaFormat3 != null) {
            frameRate = mediaFormat3.getInteger("frame-rate");
        }
        mediaFormat.setInteger("frame-rate", frameRate);
        mediaFormat.setInteger("i-frame-interval", 1);
        mediaFormat.setInteger("color-format", 21);
        this.extPrefix = extPrefix;
        mediaFormat.setInteger(this.extPrefix + KEY_ENC_VER, 0);
        mediaFormat.setInteger(this.extPrefix + KEY_ENC_TLYER, 0);
        mediaFormat.setInteger(this.extPrefix + KEY_ENC_MAXLTR, 0);
        mediaFormat.setInteger(this.extPrefix + KEY_ENC_MAXDS, 0);
        mediaFormat.setInteger(this.extPrefix + KEY_ENC_ROT, 0);
        Log.d(Commons.TAG, "Encoder format : " + this.mInputFormat);
        this.mEnc = MediaCodec.createEncoderByType(CodecUtils.MEDIA_TYPE);
        this.callbackThread = new HandlerThread("MediaCodecCallbackThread");
        this.callbackThread.start();
        this.callbackhandler = new Handler(this.callbackThread.getLooper());
        this.mEnc.setCallback(this, this.callbackhandler);
        Log.d(Commons.TAG, "configure encoder");
        this.mEnc.configure(mediaFormat, (Surface) null, (MediaCrypto) null, 1);
        Log.d(Commons.TAG, "configure encoder done");
        this.mEncOutputFormat = MediaFormat.createVideoFormat(CodecUtils.MEDIA_TYPE, width, height);
        this.mDec = MediaCodec.createDecoderByType(CodecUtils.MEDIA_TYPE);
        this.mDecConfigured = false;
    }

    public void start() {
        Log.d(Commons.TAG, "start encoder");
        this.mEnc.start();
    }

    private void _stop() {
        MediaCodec mediaCodec = this.mEnc;
        if (mediaCodec != null) {
            synchronized (mediaCodec) {
                try {
                    Log.d(Commons.TAG, "stopping encoder");
                    this.mEnc.stop();
                    this.mEnc.release();
                    this.mEnc = null;
                    Log.d(Commons.TAG, "stopped encoder");
                    this.callbackThread.quitSafely();
                    this.callbackThread.join();
                } catch (Exception e) {
                    Log.d(Commons.TAG, "Exception caught: " + e);
                }
            }
        }
    }

    public void stop() {
        this.mDone = true;
        if (this.mOutFrameCount == this.mInFrameCount) {
            _stop();
        }
    }

    public void onInputBufferAvailable(MediaCodec mediaCodec, int i) {
        int i2;
        if (!this.mDone) {
            ByteBuffer inputBuffer = this.mEnc.getInputBuffer(i);
            this.mEnc.queueInputBuffer(i, 0, inputBuffer.capacity(), this.pts, 0);
            Log.d(Commons.TAG, "input: TS=" + this.pts + " size=" + inputBuffer.capacity());
            this.mInFrameCount = this.mInFrameCount + 1;
            this.pts = this.pts + 33000;
            if (this.mDecConfigured) {
                int dequeueOutputBuffer = this.mDec.dequeueOutputBuffer(new MediaCodec.BufferInfo(), 10000);
                if (dequeueOutputBuffer == -2) {
                    this.mDecOutputFormat = this.mDec.getOutputFormat();
                    StringBuilder sb = new StringBuilder();
                    sb.append(this.mIsExynos);
                    sb.append(" ");
                    sb.append(Build.VERSION.SDK_INT);
                    sb.append(" ");
                    MediaFormat mediaFormat = this.mDecOutputFormat;
                    sb.append(!mediaFormat.containsKey(this.extPrefix + KEY_ENC_VER));
                    sb.append(" ");
                    MediaFormat mediaFormat2 = this.mDecOutputFormat;
                    sb.append(!mediaFormat2.containsKey(this.extPrefix + KEY_DEC_VER));
                    Log.d(Commons.TAG, sb.toString());
                    if (this.mIsExynos && ((i2 = Build.VERSION.SDK_INT) == 26 || i2 == 27)) {
                        MediaFormat mediaFormat3 = this.mDecOutputFormat;
                        if (!mediaFormat3.containsKey(this.extPrefix + KEY_ENC_VER)) {
                            MediaFormat mediaFormat4 = this.mDecOutputFormat;
                            if (!mediaFormat4.containsKey(this.extPrefix + KEY_DEC_VER)) {
                                Log.i(Commons.TAG, "Exynos decoder workaround, manually set version number");
                                MediaFormat mediaFormat5 = this.mDecOutputFormat;
                                mediaFormat5.setInteger(this.extPrefix + KEY_DEC_VER, ExynosDecoderDriver);
                            }
                        }
                    }
                    this.callbackCountDown.countDown();
                    Log.d(Commons.TAG, "Decoder: output format = " + this.mDecOutputFormat);
                    Log.d(Commons.TAG, "stopping decoder");
                    this.mDec.stop();
                    this.mDec.release();
                    Log.d(Commons.TAG, "stopped decoder");
                    this.mDec = null;
                    this.mDecConfigured = false;
                    stop();
                } else if (dequeueOutputBuffer > 0) {
                    Log.d(Commons.TAG, "Decoder: got output");
                    this.mDec.releaseOutputBuffer(dequeueOutputBuffer, false);
                }
            }
        }
    }

    public void onOutputBufferAvailable(MediaCodec mediaCodec, int i, MediaCodec.BufferInfo bufferInfo) {
        int dequeueInputBuffer;
        Log.d(Commons.TAG, "output: TS=" + bufferInfo.presentationTimeUs + " flags=" + bufferInfo.flags + " len=" + bufferInfo.size);
        ByteBuffer outputBuffer = this.mEnc.getOutputBuffer(i);
        if (!this.mIsEncoderOnly && this.mDecConfigured && (bufferInfo.flags & 2) == 0 && (dequeueInputBuffer = this.mDec.dequeueInputBuffer(10)) >= 0) {
            ByteBuffer inputBuffer = this.mDec.getInputBuffer(dequeueInputBuffer);
            Log.d(Commons.TAG, "Decoder: got input");
            inputBuffer.clear();
            inputBuffer.put(outputBuffer);
            this.mDec.queueInputBuffer(dequeueInputBuffer, 0, bufferInfo.size, bufferInfo.presentationTimeUs, bufferInfo.flags);
            Log.d(Commons.TAG, "Decoder: queued input ts=" + bufferInfo.presentationTimeUs + " len=" + bufferInfo.size);
        }
        this.mEnc.releaseOutputBuffer(i, false);
        this.mOutFrameCount++;
        if (this.mDone && this.mOutFrameCount == this.mInFrameCount) {
            _stop();
        }
    }

    public void onError(MediaCodec mediaCodec, MediaCodec.CodecException codecException) {
        Log.e(Commons.TAG, "ERROR : " + codecException.toString());
        this.callbackCountDown.countDown();
    }

    public void onOutputFormatChanged(MediaCodec mediaCodec, MediaFormat mediaFormat) {
        int version;
        this.mEncOutputFormat = mediaFormat;
        Log.d(Commons.TAG, "enc output format : " + mediaFormat);
        if (!this.mIsEncoderOnly) {
            mediaFormat.setInteger(this.extPrefix + "-ext-dec-picture-order.enable", 1);
            mediaFormat.setInteger(this.extPrefix + "-ext-dec-low-latency.enable", 1);
            mediaFormat.setInteger(this.extPrefix + KEY_DEC_VER, 0);
            if (this.mIsExynos && ((version = Build.VERSION.SDK_INT) == 26 || version == 27)) {
                mediaFormat.setInteger(this.extPrefix + KEY_ENC_VER, 0);
            }
            this.mDec.configure(mediaFormat, (Surface) null, (MediaCrypto) null, 0);
            this.mDec.start();
            this.mDecConfigured = true;
            Log.d(Commons.TAG, "Decoder: configured");
            return;
        }
        this.mDone = true;
        this.callbackCountDown.countDown();
    }
}